﻿#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using BreakOutBattles.Game.Items;
using BreakOutBattles.Game;
#endregion

namespace BreakOutBattles.IO
{
    #region Fields
    public enum ContentFolders
    {
        FONT,
        HUD,
        ITEMS,
        MISC,
        LEVELS,
        PARTICLES,
        BACKGROUNDS,
        THUMBS
    }
    #endregion

    public class IOManager
    {
        #region Fields
        public const string RESOURCE_DICTIONARY_PATH = @"\DB\resource_dictionary.txt";

        private static IOManager ioManager;
        private ContentManager contentManager;
        private Dictionary<ContentFolders, string> contentFolders;
        #endregion

        /// <summary>
        /// Initializes all IOmanager components.
        /// </summary>
        public void Initialize(ContentManager contentManager)
        {
            this.contentManager = contentManager;
            LoadResourceDictionary();
            LoadFolderDictionary();
        }

        private void LoadFolderDictionary()
        {
            contentFolders = new Dictionary<ContentFolders, string>();

            contentFolders[ContentFolders.BACKGROUNDS] = @"Backgrounds\";
            contentFolders[ContentFolders.PARTICLES] = @"Particles\";
            contentFolders[ContentFolders.MISC] = @"Misc\";
            contentFolders[ContentFolders.ITEMS] = @"Items\";
            contentFolders[ContentFolders.HUD] = @"Hud\";
            contentFolders[ContentFolders.FONT] = @"Font\";
            contentFolders[ContentFolders.LEVELS] = @"\Levels\";
            contentFolders[ContentFolders.THUMBS] = @"Thumbnails\";
        }

        /// <summary>
        /// Loads the resource dictionary that enables the application to use
        /// external resources in a simple way.
        /// </summary>
        private void LoadResourceDictionary()
        {
            List<string> dictionaryLines = ReadLinesFromFile(contentManager.RootDirectory + RESOURCE_DICTIONARY_PATH);

            foreach (string dictionaryLine in dictionaryLines)
            {
                string[] currentResource = dictionaryLine.Split('>');
                ResourceDictionary.AddResource(currentResource[0], currentResource[1]);
            }
        }

        /// <summary>
        /// Reads all lines from a file.
        /// </summary>
        /// <param name="path">The path to the file to read.</param>
        /// <returns>A list containing each line from the file.</returns>
        private List<string> ReadLinesFromFile(string path)
        {
            StreamReader fileReader = new StreamReader(path);
            List<string> lines = new List<string>();
            string currentLine = string.Empty;

            while ((currentLine = fileReader.ReadLine()) != null)
            {
                lines.Add(currentLine);
            }
            fileReader.Close();

            return lines;
        }

        /// <summary>
        /// Loads a texture.
        /// </summary>
        /// <param name="resourceID">The id of the resource to load.</param>
        /// <returns>A texture that correspond to the given resource id.</returns>
        public Texture2D LoadTextureFromId(string resourceID)
        {
            return LoadTexture(ContentFolders.ITEMS, ResourceDictionary.GetResource(resourceID));
        }

        /// <summary>
        /// Loads a texture from an external resource.
        /// </summary>
        /// <param name="resourceFolder">The folder where the resource is located. 
        /// Use empty string if the resource is located in the home folder.</param>
        /// <param name="resourceName">The name of the texture to load, without file extensions.</param>
        /// <returns>A texture with the spcified resource name.</returns>
        public Texture2D LoadTexture(ContentFolders contentFolder, string resourceName)
        {
            //string resourcePath = resourceFolder + "\\" +resourceName;
            return contentManager.Load<Texture2D>(contentFolders[contentFolder] + resourceName);
        }

        /// <summary>
        /// Loads a font from an external resource.
        /// </summary>
        /// <param name="fontName">The name of the font to load.</param>
        /// <returns>A font with the spcified name</returns>
        public SpriteFont LoadFont(string fontName)
        {
            return contentManager.Load<SpriteFont>(contentFolders[ContentFolders.FONT] + fontName);
        }

        /// <summary>
        /// Reads the names of all files from a specified content folder.
        /// </summary>
        /// <param name="contentFolder">The folder to get the names from.</param>
        /// <returns>A list with all file names from the specified content folder.</returns>
        public List<string> GetContentFolderNames(ContentFolders contentFolder)
        {
            string[] filePaths = Directory.GetFiles(contentManager.RootDirectory + "\\" + contentFolders[contentFolder]);
            List<string> fileNames = new List<string>();

            foreach (string filePath in filePaths)
            {
                FileInfo fileInfo = new FileInfo(filePath);
                fileNames.Add(fileInfo.Name);
            }

            return fileNames;
        }

        public LevelInfo GetLevelInfo(string levelName)
        {
            LevelInfo levelInfo = new LevelInfo();
            List<string> levelData = ReadLinesFromFile(contentManager.RootDirectory + contentFolders[ContentFolders.LEVELS] + levelName);

            levelInfo.FileName = levelName;
            levelInfo.Name = levelData[1];
            levelInfo.Description = levelData[2];
            levelInfo.Thumbnail = LoadTexture(ContentFolders.THUMBS, levelData[3]);

            return levelInfo;
        }

        public List<LevelInfo> GetLevelsInfo(List<string> levelNames)
        {
            List<LevelInfo> levelInfos = new List<LevelInfo>();

            foreach (string levelName in levelNames)
            {
                levelInfos.Add(GetLevelInfo(levelName));
            }

            return levelInfos;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="levelName"></param>
        /// <returns></returns>
        public GameLevel LoadLevel(string levelName)
        {
            GameLevel gameLevel = new GameLevel();
            List<string> levelData = ReadLinesFromFile(contentManager.RootDirectory + contentFolders[ContentFolders.LEVELS] + levelName);

            gameLevel.LevelBackground = levelData[4];
            gameLevel.DestroyableItemsCount = int.Parse(levelData[5]);
            gameLevel.BrickData = levelData.GetRange(6, levelData.Count - 6);

            return gameLevel;
        }

        /// <summary>
        /// Gets the instance of this IOManager object.
        /// </summary>
        public static IOManager Instance
        {
            get
            {
                if (ioManager == null)
                {
                    ioManager = new IOManager();
                }

                return ioManager;
            }
        }
    }
}
